
/*
 * parser_tab.c
 *
 * VT emulator parser state machine based on 
 * http://www.vt100.net/emu/dec_ansi_parser.
 *
 * 25.04.2010, Klaus Hennemann
 *
 */

#include "parser_tab.h"


#define EVENT(_id, _action, _new_state) \
        .event[_id] = { .action = (_action), .new_state = (_new_state) }

/* Events for a special column in the ascii table */
#define EVENTS_C(column, _action, _new_state) \
        EVENT(((column) << 4) | 0x00, (_action), (_new_state)),   \
        EVENT(((column) << 4) | 0x01, (_action), (_new_state)),   \
        EVENT(((column) << 4) | 0x02, (_action), (_new_state)),   \
        EVENT(((column) << 4) | 0x03, (_action), (_new_state)),   \
        EVENT(((column) << 4) | 0x04, (_action), (_new_state)),   \
        EVENT(((column) << 4) | 0x05, (_action), (_new_state)),   \
        EVENT(((column) << 4) | 0x06, (_action), (_new_state)),   \
        EVENT(((column) << 4) | 0x07, (_action), (_new_state)),   \
        EVENT(((column) << 4) | 0x08, (_action), (_new_state)),   \
        EVENT(((column) << 4) | 0x09, (_action), (_new_state)),   \
        EVENT(((column) << 4) | 0x0a, (_action), (_new_state)),   \
        EVENT(((column) << 4) | 0x0b, (_action), (_new_state)),   \
        EVENT(((column) << 4) | 0x0c, (_action), (_new_state)),   \
        EVENT(((column) << 4) | 0x0d, (_action), (_new_state)),   \
        EVENT(((column) << 4) | 0x0e, (_action), (_new_state)),   \
        EVENT(((column) << 4) | 0x0f, (_action), (_new_state))

/* vt100.net: state anywhere */
#define EVENTS_BASE                                             \
        EVENT(0x18, ACTION_EXECUTE, STATE_NULL),                \
        EVENT(0x1a, ACTION_EXECUTE, STATE_NULL),                \
        EVENT(0x1b, ACTION_NULL, STATE_ESCAPE),                 \
        EVENTS_C(8, ACTION_EXECUTE, STATE_NULL),                \
        EVENT(0x90, ACTION_NULL, STATE_DCS_ENTRY),              \
        EVENT(0x91, ACTION_EXECUTE, STATE_NULL),                \
        EVENT(0x92, ACTION_EXECUTE, STATE_NULL),                \
        EVENT(0x93, ACTION_EXECUTE, STATE_NULL),                \
        EVENT(0x94, ACTION_EXECUTE, STATE_NULL),                \
        EVENT(0x95, ACTION_EXECUTE, STATE_NULL),                \
        EVENT(0x96, ACTION_EXECUTE, STATE_NULL),                \
        EVENT(0x97, ACTION_EXECUTE, STATE_NULL),                \
        EVENT(0x98, ACTION_NULL, STATE_SOS_PM_APC_STRING),      \
        EVENT(0x99, ACTION_EXECUTE, STATE_NULL),                \
        EVENT(0x9a, ACTION_EXECUTE, STATE_NULL),                \
        EVENT(0x9b, ACTION_NULL, STATE_CSI_ENTRY),              \
        EVENT(0x9c, ACTION_NULL, STATE_NULL),                   \
        EVENT(0x9d, ACTION_NULL, STATE_OSC_STRING),             \
        EVENT(0x9e, ACTION_NULL, STATE_SOS_PM_APC_STRING),      \
        EVENT(0x9f, ACTION_NULL, STATE_SOS_PM_APC_STRING)

/* Events 0x00-0x17, 0x19, 0x1C-0x1F */
#define EVENTS_C0_C1(_action, _new_state)               \
        EVENTS_C(0, (_action), (_new_state)),           \
        EVENT(0x10, (_action), (_new_state)),           \
        EVENT(0x11, (_action), (_new_state)),           \
        EVENT(0x12, (_action), (_new_state)),           \
        EVENT(0x13, (_action), (_new_state)),           \
        EVENT(0x14, (_action), (_new_state)),           \
        EVENT(0x15, (_action), (_new_state)),           \
        EVENT(0x16, (_action), (_new_state)),           \
        EVENT(0x17, (_action), (_new_state)),           \
        EVENT(0x19, (_action), (_new_state)),           \
        EVENT(0x1c, (_action), (_new_state)),           \
        EVENT(0x1d, (_action), (_new_state)),           \
        EVENT(0x1e, (_action), (_new_state)),           \
        EVENT(0x1f, (_action), (_new_state)) 

/* Events 0x20-0x7f */
#define EVENTS_C2_TO_C7(_action, _new_state)            \
        EVENTS_C(2, (_action), (_new_state)),           \
        EVENTS_C(3, (_action), (_new_state)),           \
        EVENTS_C(4, (_action), (_new_state)),           \
        EVENTS_C(5, (_action), (_new_state)),           \
        EVENTS_C(6, (_action), (_new_state)),           \
        EVENTS_C(7, (_action), (_new_state))

/* Events 0x70-0x7e */
#define EVENTS_70_TO_7E(_action, _new_state)            \
        EVENT(0x70, (_action), (_new_state)),           \
        EVENT(0x71, (_action), (_new_state)),           \
        EVENT(0x72, (_action), (_new_state)),           \
        EVENT(0x73, (_action), (_new_state)),           \
        EVENT(0x74, (_action), (_new_state)),           \
        EVENT(0x75, (_action), (_new_state)),           \
        EVENT(0x76, (_action), (_new_state)),           \
        EVENT(0x77, (_action), (_new_state)),           \
        EVENT(0x78, (_action), (_new_state)),           \
        EVENT(0x79, (_action), (_new_state)),           \
        EVENT(0x7a, (_action), (_new_state)),           \
        EVENT(0x7b, (_action), (_new_state)),           \
        EVENT(0x7c, (_action), (_new_state)),           \
        EVENT(0x7d, (_action), (_new_state)),           \
        EVENT(0x7e, (_action), (_new_state))


      
static const struct State state_ground = {
        .id = STATE_GROUND,

        EVENTS_BASE,
        EVENTS_C0_C1(ACTION_EXECUTE, STATE_NULL),
        EVENTS_C2_TO_C7(ACTION_PRINT, STATE_NULL),
        EVENTS_C(0xa, ACTION_PRINT, STATE_NULL),
        EVENTS_C(0xb, ACTION_PRINT, STATE_NULL),
        EVENTS_C(0xc, ACTION_PRINT, STATE_NULL),
        EVENTS_C(0xd, ACTION_PRINT, STATE_NULL),
        EVENTS_C(0xe, ACTION_PRINT, STATE_NULL),
        EVENTS_C(0xf, ACTION_PRINT, STATE_NULL),

	/* wide characters */
	EVENT(EVENT_WCHAR, ACTION_PRINT, STATE_NULL)
};

static const struct State state_escape = {
        .id = STATE_ESCAPE,
        .entry = ACTION_CLEAR,

        EVENTS_BASE,
        EVENTS_C0_C1(ACTION_EXECUTE, STATE_NULL),

        /* to ground */
        EVENTS_C(3, ACTION_ESC_DISPATCH, STATE_GROUND),
        EVENTS_C(4, ACTION_ESC_DISPATCH, STATE_GROUND),
        EVENT(0x51, ACTION_ESC_DISPATCH, STATE_GROUND),
        EVENT(0x52, ACTION_ESC_DISPATCH, STATE_GROUND),
        EVENT(0x53, ACTION_ESC_DISPATCH, STATE_GROUND),
        EVENT(0x54, ACTION_ESC_DISPATCH, STATE_GROUND),
        EVENT(0x55, ACTION_ESC_DISPATCH, STATE_GROUND),
        EVENT(0x56, ACTION_ESC_DISPATCH, STATE_GROUND),
        EVENT(0x57, ACTION_ESC_DISPATCH, STATE_GROUND),
        EVENT(0x59, ACTION_ESC_DISPATCH, STATE_GROUND),
        EVENT(0x5a, ACTION_ESC_DISPATCH, STATE_GROUND),
        EVENT(0x5c, ACTION_ESC_DISPATCH, STATE_GROUND),
        EVENTS_C(6, ACTION_ESC_DISPATCH, STATE_GROUND),
        EVENTS_70_TO_7E(ACTION_ESC_DISPATCH, STATE_GROUND),

        /* to escape_intermediate */
        EVENTS_C(2, ACTION_COLLECT, STATE_ESCAPE_INTERMEDIATE),

        /* to sos_pm_apc_string */
        EVENT(0x58, ACTION_NULL, STATE_SOS_PM_APC_STRING),
        EVENT(0x5e, ACTION_NULL, STATE_SOS_PM_APC_STRING),
        EVENT(0x5f, ACTION_NULL, STATE_SOS_PM_APC_STRING),

        /* to dcs_entry */
        EVENT(0x50, ACTION_NULL, STATE_DCS_ENTRY),

        /* to osc_string */
        EVENT(0x5d, ACTION_NULL, STATE_OSC_STRING),

        /* to csi_entry */
        EVENT(0x5b, ACTION_NULL, STATE_CSI_ENTRY)
};

static const struct State state_escape_intermediate = {
        .id = STATE_ESCAPE_INTERMEDIATE,

        EVENTS_BASE,
        EVENTS_C0_C1(ACTION_EXECUTE, STATE_NULL),
        EVENTS_C(2, ACTION_COLLECT, STATE_NULL),

        /* to ground */
        EVENTS_C(3, ACTION_ESC_DISPATCH, STATE_GROUND),
        EVENTS_C(4, ACTION_ESC_DISPATCH, STATE_GROUND),
        EVENTS_C(5, ACTION_ESC_DISPATCH, STATE_GROUND),
        EVENTS_C(6, ACTION_ESC_DISPATCH, STATE_GROUND),
        EVENTS_70_TO_7E(ACTION_ESC_DISPATCH, STATE_GROUND)
};

static const struct State state_csi_entry = {
        .id = STATE_CSI_ENTRY,
        .entry = ACTION_CLEAR,

        EVENTS_BASE,
        EVENTS_C0_C1(ACTION_EXECUTE, STATE_NULL),

        /* to csi_intermediate */
        EVENTS_C(2, ACTION_COLLECT, STATE_CSI_INTERMEDIATE),

        /* to csi_ignore */
        EVENT(0x3a, ACTION_NULL, STATE_CSI_IGNORE),

        /* to csi_param */
        EVENT(0x30, ACTION_PARAM, STATE_CSI_PARAM),
        EVENT(0x31, ACTION_PARAM, STATE_CSI_PARAM),
        EVENT(0x32, ACTION_PARAM, STATE_CSI_PARAM),
        EVENT(0x33, ACTION_PARAM, STATE_CSI_PARAM),
        EVENT(0x34, ACTION_PARAM, STATE_CSI_PARAM),
        EVENT(0x35, ACTION_PARAM, STATE_CSI_PARAM),
        EVENT(0x36, ACTION_PARAM, STATE_CSI_PARAM),
        EVENT(0x37, ACTION_PARAM, STATE_CSI_PARAM),
        EVENT(0x38, ACTION_PARAM, STATE_CSI_PARAM),
        EVENT(0x39, ACTION_PARAM, STATE_CSI_PARAM),
        EVENT(0x3b, ACTION_PARAM, STATE_CSI_PARAM),
        EVENT(0x3c, ACTION_COLLECT, STATE_CSI_PARAM),
        EVENT(0x3d, ACTION_COLLECT, STATE_CSI_PARAM),
        EVENT(0x3e, ACTION_COLLECT, STATE_CSI_PARAM),
        EVENT(0x3f, ACTION_COLLECT, STATE_CSI_PARAM),

        /* to ground */
        EVENTS_C(4, ACTION_CSI_DISPATCH, STATE_GROUND),
        EVENTS_C(5, ACTION_CSI_DISPATCH, STATE_GROUND),
        EVENTS_C(6, ACTION_CSI_DISPATCH, STATE_GROUND),
        EVENTS_70_TO_7E(ACTION_CSI_DISPATCH, STATE_GROUND)
};

static const struct State state_csi_param = {
        .id = STATE_CSI_PARAM, 

        EVENTS_BASE,
        EVENTS_C0_C1(ACTION_EXECUTE, STATE_NULL),
        EVENT(0x30, ACTION_PARAM, STATE_NULL),
        EVENT(0x31, ACTION_PARAM, STATE_NULL),
        EVENT(0x32, ACTION_PARAM, STATE_NULL),
        EVENT(0x33, ACTION_PARAM, STATE_NULL),
        EVENT(0x34, ACTION_PARAM, STATE_NULL),
        EVENT(0x35, ACTION_PARAM, STATE_NULL),
        EVENT(0x36, ACTION_PARAM, STATE_NULL),
        EVENT(0x37, ACTION_PARAM, STATE_NULL),
        EVENT(0x38, ACTION_PARAM, STATE_NULL),
        EVENT(0x39, ACTION_PARAM, STATE_NULL),
        EVENT(0x3b, ACTION_PARAM, STATE_NULL),

        /* to ground */
        EVENTS_C(4, ACTION_CSI_DISPATCH, STATE_GROUND),
        EVENTS_C(5, ACTION_CSI_DISPATCH, STATE_GROUND),
        EVENTS_C(6, ACTION_CSI_DISPATCH, STATE_GROUND),
        EVENTS_70_TO_7E(ACTION_CSI_DISPATCH, STATE_GROUND),

        /* to csi_ignore */
        EVENT(0x3a, ACTION_NULL, STATE_CSI_IGNORE),
        EVENT(0x3c, ACTION_NULL, STATE_CSI_IGNORE),
        EVENT(0x3d, ACTION_NULL, STATE_CSI_IGNORE),
        EVENT(0x3e, ACTION_NULL, STATE_CSI_IGNORE),
        EVENT(0x3f, ACTION_NULL, STATE_CSI_IGNORE),

        /* to csi_intermediate */
        EVENTS_C(2, ACTION_COLLECT, STATE_CSI_INTERMEDIATE)
};

static const struct State state_csi_intermediate = {
        .id = STATE_CSI_INTERMEDIATE,

        EVENTS_BASE,
        EVENTS_C0_C1(ACTION_EXECUTE, STATE_NULL),
        EVENTS_C(2, ACTION_COLLECT, STATE_NULL),

        /* to ground */
        EVENTS_C(4, ACTION_CSI_DISPATCH, STATE_GROUND),
        EVENTS_C(5, ACTION_CSI_DISPATCH, STATE_GROUND),
        EVENTS_C(6, ACTION_CSI_DISPATCH, STATE_GROUND),
        EVENTS_70_TO_7E(ACTION_CSI_DISPATCH, STATE_GROUND),

        /* to csi_ignore */
        EVENTS_C(3, ACTION_NULL, STATE_CSI_IGNORE)
};

static const struct State state_csi_ignore = {
        .id = STATE_CSI_IGNORE,

        EVENTS_BASE,
        EVENTS_C0_C1(ACTION_EXECUTE, STATE_NULL),

         /* to ground */
        EVENTS_C(4, ACTION_NULL, STATE_GROUND),
        EVENTS_C(5, ACTION_NULL, STATE_GROUND),
        EVENTS_C(6, ACTION_NULL, STATE_GROUND),
        EVENTS_70_TO_7E(ACTION_NULL, STATE_GROUND)
   };

static const struct State state_dcs_entry = {
        .id = STATE_DCS_ENTRY,
        .entry = ACTION_CLEAR,

        EVENTS_BASE,

        /* to dcs_intermediate */
        EVENTS_C(2, ACTION_COLLECT, STATE_DCS_INTERMEDIATE),

        /* to dcs_ignore */
        EVENT(0x3a, ACTION_NULL, STATE_DCS_IGNORE),

        /* to dcs_param */
        EVENT(0x30, ACTION_PARAM, STATE_DCS_PARAM),
        EVENT(0x31, ACTION_PARAM, STATE_DCS_PARAM),
        EVENT(0x32, ACTION_PARAM, STATE_DCS_PARAM),
        EVENT(0x33, ACTION_PARAM, STATE_DCS_PARAM),
        EVENT(0x34, ACTION_PARAM, STATE_DCS_PARAM),
        EVENT(0x35, ACTION_PARAM, STATE_DCS_PARAM),
        EVENT(0x36, ACTION_PARAM, STATE_DCS_PARAM),
        EVENT(0x37, ACTION_PARAM, STATE_DCS_PARAM),
        EVENT(0x38, ACTION_PARAM, STATE_DCS_PARAM),
        EVENT(0x39, ACTION_PARAM, STATE_DCS_PARAM),
        EVENT(0x3b, ACTION_PARAM, STATE_DCS_PARAM),
        EVENT(0x3c, ACTION_COLLECT, STATE_DCS_PARAM),
        EVENT(0x3d, ACTION_COLLECT, STATE_DCS_PARAM),
        EVENT(0x3e, ACTION_COLLECT, STATE_DCS_PARAM),
        EVENT(0x3f, ACTION_COLLECT, STATE_DCS_PARAM),

        /* to dcs_passthrough */
        EVENTS_C(4, ACTION_NULL, STATE_DCS_PASSTHROUGH),
        EVENTS_C(5, ACTION_NULL, STATE_DCS_PASSTHROUGH),
        EVENTS_C(6, ACTION_NULL, STATE_DCS_PASSTHROUGH),
        EVENTS_70_TO_7E(ACTION_NULL, STATE_DCS_PASSTHROUGH)
};

static const struct State state_dcs_param = {
        .id = STATE_DCS_PARAM,
        
        EVENTS_BASE,
        EVENT(0x30, ACTION_PARAM, STATE_NULL),
        EVENT(0x31, ACTION_PARAM, STATE_NULL),
        EVENT(0x32, ACTION_PARAM, STATE_NULL),
        EVENT(0x33, ACTION_PARAM, STATE_NULL),
        EVENT(0x34, ACTION_PARAM, STATE_NULL),
        EVENT(0x35, ACTION_PARAM, STATE_NULL),
        EVENT(0x36, ACTION_PARAM, STATE_NULL),
        EVENT(0x37, ACTION_PARAM, STATE_NULL),
        EVENT(0x38, ACTION_PARAM, STATE_NULL),
        EVENT(0x39, ACTION_PARAM, STATE_NULL),
        EVENT(0x3b, ACTION_PARAM, STATE_NULL),

        /* to dcs_ignore */
        EVENT(0x3a, ACTION_NULL, STATE_DCS_IGNORE),
        EVENT(0x3c, ACTION_NULL, STATE_DCS_IGNORE),
        EVENT(0x3d, ACTION_NULL, STATE_DCS_IGNORE),
        EVENT(0x3e, ACTION_NULL, STATE_DCS_IGNORE),
        EVENT(0x3f, ACTION_NULL, STATE_DCS_IGNORE),

        /* to dcs_intermediate */
        EVENTS_C(2, ACTION_COLLECT, STATE_DCS_INTERMEDIATE),

        /* to dcs_passthrough */
        EVENTS_C(4, ACTION_NULL, STATE_DCS_PASSTHROUGH),
        EVENTS_C(5, ACTION_NULL, STATE_DCS_PASSTHROUGH),
        EVENTS_C(6, ACTION_NULL, STATE_DCS_PASSTHROUGH),
        EVENTS_70_TO_7E(ACTION_NULL, STATE_DCS_PASSTHROUGH)
};

static const struct State state_dcs_intermediate = {
        .id = STATE_DCS_INTERMEDIATE,

        EVENTS_BASE,
        EVENTS_C(2, ACTION_COLLECT, STATE_NULL),

        /* to dcs_ignore */
        EVENTS_C(3, ACTION_NULL, STATE_DCS_IGNORE),

        /* to dcs_passthrough */
        EVENTS_C(4, ACTION_NULL, STATE_DCS_PASSTHROUGH),
        EVENTS_C(5, ACTION_NULL, STATE_DCS_PASSTHROUGH),
        EVENTS_C(6, ACTION_NULL, STATE_DCS_PASSTHROUGH),
        EVENTS_70_TO_7E(ACTION_NULL, STATE_DCS_PASSTHROUGH)
};

static const struct State state_dcs_passthrough = {
        .id = STATE_DCS_PASSTHROUGH,
        .entry = ACTION_HOOK,
        .exit  = ACTION_UNHOOK,

        EVENTS_BASE,
        EVENTS_C0_C1(ACTION_PUT, STATE_NULL),
        EVENTS_C(2, ACTION_PUT, STATE_NULL),
        EVENTS_C(3, ACTION_PUT, STATE_NULL),
        EVENTS_C(4, ACTION_PUT, STATE_NULL),
        EVENTS_C(5, ACTION_PUT, STATE_NULL),
        EVENTS_C(6, ACTION_PUT, STATE_NULL),
        EVENTS_70_TO_7E(ACTION_PUT, STATE_NULL),

        /* to ground */
        EVENT(0x9c, ACTION_NULL, STATE_GROUND)
};

static const struct State state_dcs_ignore = {
        .id = STATE_DCS_IGNORE,

        EVENTS_BASE,

        /* to ground */
        EVENT(0x9c, ACTION_NULL, STATE_GROUND)
};

static const struct State state_osc_string = {
        .id = STATE_OSC_STRING,
        .entry = ACTION_OSC_START,
        .exit  = ACTION_OSC_END,

        EVENTS_BASE,
        EVENTS_C2_TO_C7(ACTION_OSC_PUT, STATE_NULL),

        /* to ground */
        EVENT(0x9c, ACTION_NULL, STATE_GROUND)
};

static const struct State state_sos_pm_apc_string = {
        .id = STATE_SOS_PM_APC_STRING,

        EVENTS_BASE,

        /* to ground */
        EVENT(0x9c, ACTION_NULL, STATE_GROUND)
};


/* table of all states */
const struct State * parser_state_tab[STATE_COUNT] = {
        0,
        &state_ground,
        &state_escape,
        &state_escape_intermediate,
        &state_csi_entry,
        &state_csi_param,
        &state_csi_intermediate,
        &state_csi_ignore,
        &state_dcs_entry,
        &state_dcs_param,
        &state_dcs_intermediate,
        &state_dcs_passthrough,
        &state_dcs_ignore,
        &state_osc_string,
        &state_sos_pm_apc_string
};


